package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.UserPrivilegeConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.admin.UserVocAISituationDTO;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.AIReviewReadCommand;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserFavoriteCommand;
import com.cskaoyan.wordmemorize.request.UserVocExampleSentenceCommand;
import com.cskaoyan.wordmemorize.service.UserPrivilegeService;

import org.apache.ibatis.executor.BatchResult;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserPrivilegeServiceImpl extends ServiceImpl<UserVocAISituationMapper, UserVocAISituationDO> implements UserPrivilegeService {

    @Autowired
    UserVocAISituationMapper userVocAISituationMapper;
    @Autowired
    UserPrivilegeConverter userPrivilegeConverter;
    @Autowired
    UserFavoriteMapper userFavoriteMapper;
    @Autowired
    UserVocExampleSentenceMapper userVocExampleSentenceMapper;
    @Autowired
    private VocChapBookMapper vocChapBookMapper;
    @Autowired
    private UserVocRevMapper userVocRevMapper;
    @Autowired
    private VocMeaningMapper vocMeaningMapper;
    @Autowired
    UserNotRememberMapper userNotRememberMapper;
    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Autowired
    UserVocBoundLogMapper userVocBoundLogMapper;
    @Autowired
    UserPrivilegeHistoryMapper userPrivilegeHistoryMapper;
    @Value("classpath:/prompt/ai-read-system-message.st")
    private Resource systemResource;
    @Value("classpath:/prompt/ai-read-user-message.st")
    private Resource userResource;


    private final ChatClient chatClient;

    // Spring自动注入ChatClient.Builder对象
    public UserPrivilegeServiceImpl(ChatClient.Builder chatClientBuilder) {
        // 利用Builder对象的build()方法创建出ChatClient对象
        this.chatClient = chatClientBuilder.build();
    }


    // APP端获取词书进度
    @Override
    public UserVocBookStatisticsDTO getSelectedBookStatistics(Long userId, Long bookId) {
        // 1. 查询该书籍下所有单词id（voc_chap_book表）
        // 批量查询该书籍下所有单词
        List<VocChapBookDO> vocChapBookList = vocChapBookMapper.selectList(
                new LambdaQueryWrapper<VocChapBookDO>()
                        .eq(VocChapBookDO::getBookId, bookId)
        );
        // 提取 vocId 列表
        List<Long> vocIds = vocChapBookList.stream()
                .map(VocChapBookDO::getVocId)
                .toList();
        int total = vocIds.size();

        // 2. 查询该用户在该书籍下所有已选单词的复习记录（user_voc_rev表）
        List<UserVocRevDO> userVocRevList = userVocRevMapper.selectList(
                new LambdaQueryWrapper<UserVocRevDO>()
                        .eq(UserVocRevDO::getUserId, userId)
                        .in(!vocIds.isEmpty(), UserVocRevDO::getVocId, vocIds)
        );

        // 3. 统计各类单词数量
        int notStarted = 0; // 已选未学 type=0
        int familiar = 0;   // 熟悉（复习间隔 >= 365，type=1）
        int general = 0;    // 一般（复习间隔 < 365，type=1）
        int unFamiliar = 0; // 不熟（复习间隔=1，type=1）

        for (UserVocRevDO userVocRevDO : userVocRevList) {
            if (userVocRevDO.getType() != null && userVocRevDO.getType() == 0) {
                notStarted++;
            } else if (userVocRevDO.getType() != null && userVocRevDO.getType() == 1) {
                //  判断复习间隔 (interval)
                Integer interval = userVocRevDO.getReviewInterval();
                if (interval != null) {
                    if (interval >= 365) {
                        familiar++;
                    } else if (interval == 1) {
                        unFamiliar++;
                    } else {
                        general++;
                    }
                } else {
                    // 当interval为null，则默认熟悉程度为一般
                    general++;
                }
            }
        }

        // 4. 计算未选单词数量
        int selected = userVocRevList.size();
        int unSelected = total - selected;

        // 5. 封装DTO
        UserVocBookStatisticsDTO dto = new UserVocBookStatisticsDTO();
        dto.setTotal(total);
        dto.setNotStarted(notStarted);
        dto.setGeneral(general);
        dto.setFamiliar(familiar);
        dto.setUnFamiliar(unFamiliar);
        dto.setUnSelected(unSelected);

        return dto;
    }


    @Override
    public void addFavoriteBulk(List<UserFavoriteCommand> userFavoriteCommand, Long userId) {
        List<UserFavoriteDO> userFavoriteDOS = userPrivilegeConverter.userFavoriteDOs2DTOs(userFavoriteCommand);
        List<BatchResult> insert = userFavoriteMapper.insert(userFavoriteDOS);
        System.out.println(insert);
    }


    @Override
    public void addFavorite(UserFavoriteCommand userFavoriteCommand, Long userId) {
        UserFavoriteDO userFavoriteDO = userPrivilegeConverter.userFavoriteCommand2DO(userFavoriteCommand);
        int insert = userFavoriteMapper.insert(userFavoriteDO);
        System.out.println(insert);

    }

    @Override
    public void cancelFavorite(List<Long> ids, Long userId) {

        int delete = userFavoriteMapper.delete(new LambdaQueryWrapper<UserFavoriteDO>()
                .eq(UserFavoriteDO::getUserId, userId)
                .in(UserFavoriteDO::getVocId, ids));
        System.out.println(delete);

    }


    // 获取用户收藏单词列表
    @Override
    public PageDTO<UserFavoriteDTO> getUserFavoriteList(PageRequest pageRequest, Long userId) {
        // 1. 构造分页对象，pageNum为当前页码，count为每页条数
        Page<UserFavoriteDO> page = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());

        // 2. 构造查询条件
        LambdaQueryWrapper<UserFavoriteDO> wrapper = new LambdaQueryWrapper<>();
        // 查当前用户的收藏
        wrapper.eq(UserFavoriteDO::getUserId, userId);
        // 查未逻辑删除的数据（实体类isDeleted字段加了@TableLogic注解，可省略）
        // wrapper.eq(UserFavoriteDO::getIsDeleted, 0);

        // 3. 分页查询 user_favorite 表
        Page<UserFavoriteDO> favoritePage = userFavoriteMapper.selectPage(page, wrapper);

        // 4. 先用 MapStruct 转换器将分页的 DO 列表和总数组装成 PageDTO<UserFavoriteDTO>
        // 此时只映射了简单字段（user_favorite表里只有对应vocId、vocContent、selected字段的列）
        PageDTO<UserFavoriteDTO> result = userPrivilegeConverter
                .userFavoriteDOPage2PageDTO(favoritePage.getRecords(), favoritePage.getTotal());

        // 5. 遍历分页结果中的每个 UserFavoriteDTO，补充释义（interpretations）
        for (UserFavoriteDTO dto : result.getPageList()) {
            Long vocId = Long.valueOf(dto.getVocId());

            // 5.1 查询该单词的所有释义（voc_meaning 表，可能有多条）
            List<VocMeaningDO> meanings = vocMeaningMapper.selectList(
                    new LambdaQueryWrapper<VocMeaningDO>().eq(VocMeaningDO::getVocId, vocId)
            );
            // 5.2 将释义 DO 转换为前端需要的 DTO，并组装到 interpretations 字段
            List<DisplayVocInterpretationDTO> interpretationDTOs = meanings.stream()
                    .map(userPrivilegeConverter::vocMeaningDO2DTO) // MapStruct 映射
                    .map(m -> {
                        // 这里再次手动组装，确保字段完整
                        DisplayVocInterpretationDTO d = new DisplayVocInterpretationDTO();
                        d.setId(m.getId());
                        d.setType(m.getType());
                        d.setContent(m.getInterContent());  // 释义内容
                        return d;
                    }).toList();
            dto.setInterpretations(interpretationDTOs);

        }

        // 6. 返回最终分页结果
        return result;

    }

    @Override
    public void addUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {

        UserVocExampleSentenceDO userVocExampleSentenceDO =
                userPrivilegeConverter.userVocExampleSentenceCommand2DO(command);
        userVocExampleSentenceDO.setUserId(userId);
        int insert = userVocExampleSentenceMapper.insert(userVocExampleSentenceDO);

    }

    @Override
    public PageDTO<DisplayUserVocSentenceDTO> getUserVocSentence(PageRequest pageRequest, Long userId) {

        // 页数
        Integer pageNum = pageRequest.getPageNum();
        // 每页的数据量
        Integer count = pageRequest.getCount();
//        Page<UserVocExampleSentenceDO> userVocExampleSentenceDOPage = new Page<>(pageNum,count);
//
//        LambdaQueryWrapper<UserVocExampleSentenceDO> eq = new LambdaQueryWrapper<UserVocExampleSentenceDO>()
//                .eq(UserVocExampleSentenceDO::getUserId,userId);
//        // 判断是否传了keyword
//        String keyword = pageRequest.getKeyword();
//        if(keyword == null || "".equals(keyword)){
//            eq.eq(UserVocExampleSentenceDO::getVocContent,keyword);
//        }
//
//        // 获取Sentences -> userVocSentenceDTOS
//        userVocExampleSentenceMapper.selectPage(userVocExampleSentenceDOPage, eq);
//        List<UserVocExampleSentenceDO> records = userVocExampleSentenceDOPage.getRecords();
//        List<UserVocSentenceDTO> userVocSentenceDTOS = userPrivilegeConverter.userVocSentenceDOs2DTOs(records);
//
//        // 获取vocId
//        Map<String,Object> map = new HashMap<>();
//        map.put("voc_content", keyword);
//        List<UserVocExampleSentenceDO> userVocExampleSentenceDOS = userVocExampleSentenceMapper.selectByMap(map);
//        Long vocId = userVocExampleSentenceDOS.get(0).getVocId();
//
//        DisplayUserVocSentenceDTO displayUserVocSentenceDTO = new DisplayUserVocSentenceDTO();
//        displayUserVocSentenceDTO.setSentences(userVocSentenceDTOS);
//
//        displayUserVocSentenceDTO.setVocId(String.valueOf(vocId));
//        displayUserVocSentenceDTO.setVocContent(keyword);
//        // TODO 待转换
        List<DisplayUserVocSentenceDTO> displayUserVocSentenceDTOS
                = userVocExampleSentenceMapper.queryListSentenceByUserIdAndKeyword(pageRequest.getKeyword(), userId);

        List<DisplayUserVocSentenceDTO> collect = displayUserVocSentenceDTOS.stream()
                .skip(count * (pageNum - 1))
                .limit(count)
                .collect(Collectors.toList());
        PageDTO<DisplayUserVocSentenceDTO> displayUserVocSentenceDTOPageDTO = new PageDTO<>();

        displayUserVocSentenceDTOPageDTO.setPageList(collect);
        displayUserVocSentenceDTOPageDTO.setTotalCount((long) displayUserVocSentenceDTOS.size());
        return displayUserVocSentenceDTOPageDTO;
    }


    @Override
    public void updateUserVocSentence(UserVocExampleSentenceCommand command, Long userId) {

        UserVocExampleSentenceDO userVocExampleSentenceDO =
                userPrivilegeConverter.userVocExampleSentenceCommand2DO(command);

        userVocExampleSentenceMapper.update(userVocExampleSentenceDO, new LambdaQueryWrapper<UserVocExampleSentenceDO>()
                .eq(UserVocExampleSentenceDO::getId, command.getId()));
    }

    // APP端删除用户自建例句
    @Override
    public void deleteUserVocSentence(Long id) {
        Long userId = StpKit.USER.getLoginIdAsLong(); // 获取当前登录用户id
        QueryWrapper<UserVocExampleSentenceDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id).eq("user_id", userId); // 只能删自己的例句
        userVocExampleSentenceMapper.delete(queryWrapper);

    }

    @Override
    public void notRemember(Long vocId, Long userId) {

        UpdateWrapper<UserNotRememberDO> eq = new UpdateWrapper<UserNotRememberDO>()
                .eq("user_id", userId)
                .eq("voc_id", vocId)
                .set("is_deleted", "1");
        userNotRememberMapper.update(null, eq);

        LambdaQueryWrapper<UserVocRevDO> userVocRevMapperLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userVocRevMapperLambdaQueryWrapper
                .eq(UserVocRevDO::getUserId, userId)
                .eq(UserVocRevDO::getVocId, vocId);
        if (userVocRevMapper.selectOne(userVocRevMapperLambdaQueryWrapper) != null) {
            UpdateWrapper<UserVocRevDO> set = new UpdateWrapper<UserVocRevDO>()
                    .eq("user_id", userId)
                    .eq("voc_id", vocId)
                    .set("is_deleted", "1");
            userVocRevMapper.update(null, set);
        }

    }

    @Override
    public void cancelNotRemember(Long vocId, Long userId) {

        UpdateWrapper<UserNotRememberDO> eq = new UpdateWrapper<UserNotRememberDO>()
                .eq("user_id", userId)
                .eq("voc_id", vocId)
                .set("is_deleted", "0");
        userNotRememberMapper.update(null, eq);

        LambdaQueryWrapper<UserVocRevDO> userVocRevMapperLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userVocRevMapperLambdaQueryWrapper
                .eq(UserVocRevDO::getUserId, userId)
                .eq(UserVocRevDO::getVocId, vocId);
        if (userVocRevMapper.selectOne(userVocRevMapperLambdaQueryWrapper) != null) {
            UpdateWrapper<UserVocRevDO> set = new UpdateWrapper<UserVocRevDO>()
                    .eq("user_id", userId)
                    .eq("voc_id", vocId)
                    .set("is_deleted", "0");
            userVocRevMapper.update(null, set);
        }
    }

    @Override
    public List<UserReviewFillWordDTO> getUserReviewFillWordTopics(List<Long> vocIds) {
        return null;
    }

    @Override
    public List<UserReviewSingleChoiceDTO> getVocSingleChoiceTopic(List<Long> vocIds) {
        return null;
    }


    // 获取AI阅读风格
    @Override
    public List<UserVocAISituationDTO> getAIReviewReadOptions() {
        List<UserVocAISituationDO> userVocAISituationDOS = userVocAISituationMapper.queryAllWithUserVocAISituationOptionsList();
        List<UserVocAISituationDTO> userVocAISituationDTOS = userPrivilegeConverter.userVocAISituationDOs2DTOs(userVocAISituationDOS);
        return userVocAISituationDTOS;
    }

    // APP端获取用户剩余免费AI阅读次数
    @Override
    public Integer getUserVocAIReadRemainFreeCount(Long userId) {
        Integer freeCountForAI = userVocAISituationMapper.getFreeCountForAI(userId);
        return freeCountForAI;
    }


    @Override
    public List<AIReviewReadDTO> getAIReviewReadContent(AIReviewReadCommand command, Long userId) {
        // 获取AI阅读结果

        try {
            // 1. 计算单词使用量
            int wordCount = command.getVocList().size();

            // 2. 查询单词上限是否满足
            UserVocBoundStatisticsDO statisticsDO = userVocBoundStatisticsMapper.selectOne(
                    new LambdaQueryWrapper<UserVocBoundStatisticsDO>()
                            .eq(UserVocBoundStatisticsDO::getUserId, userId)
                            .eq(UserVocBoundStatisticsDO::getIsDeleted, 0)
            );

            if (statisticsDO == null || statisticsDO.getAvailable() < wordCount) {
                throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
            }

            // 更新单词上限
            LambdaUpdateWrapper<UserVocBoundStatisticsDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper
                    .eq(UserVocBoundStatisticsDO::getUserId, userId)
                    .eq(UserVocBoundStatisticsDO::getAvailable, statisticsDO.getAvailable())
                    .setSql("available = available - " + wordCount)
                    .setSql("occupied = occupied + " + wordCount);

            int updateRows = userVocBoundStatisticsMapper.update(null, updateWrapper);
            if (updateRows == 0) {
                log.error("单词上限更新失败");
                throw new BusinessException(ResultCodeEnum.USER_VOC_BOUND_NOT_ENOUGH);
            }

            // 3. 添加单词上限变化日志
            UserVocBoundLogDO userVocBoundLogDO = new UserVocBoundLogDO();
            userVocBoundLogDO.setUserId(userId);
            userVocBoundLogDO.setType(3); // 3表示消费
            userVocBoundLogDO.setCount(-wordCount); // 变化数量
            userVocBoundLogDO.setLogDate(LocalDate.now());
            userVocBoundLogDO.setDescription("AI阅读功能消耗" + wordCount + "个单词上限");
            userVocBoundLogMapper.insert(userVocBoundLogDO);

            // 4. 更新特权使用统计
            LambdaQueryWrapper<UserPrivilegeUseStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper
                    .eq(UserPrivilegeUseStatisticsDO::getUserId, userId)
                    .eq(UserPrivilegeUseStatisticsDO::getIsDeleted, 0);

            UserPrivilegeUseStatisticsDO privilege = userPrivilegeHistoryMapper.selectOne(queryWrapper);

            if (privilege == null) {
                // 首次使用，插入记录
                privilege = new UserPrivilegeUseStatisticsDO();
                privilege.setUserId(userId);
                privilege.setPrivilegeCode("review:ai:read");
                privilege.setUseCount(1);
                userPrivilegeHistoryMapper.insert(privilege);
            } else {
                // 已存在，更新使用次数
                LambdaUpdateWrapper<UserPrivilegeUseStatisticsDO> privilegeUpdateWrapper = new LambdaUpdateWrapper<>();
                privilegeUpdateWrapper
                        .eq(UserPrivilegeUseStatisticsDO::getId, privilege.getId())
                        .set(UserPrivilegeUseStatisticsDO::getUseCount, privilege.getUseCount() + 1);

                userPrivilegeHistoryMapper.update(null, privilegeUpdateWrapper);
            }
            // 5. 调用AI模型
            Map<String, Object> userModel = Map.of(
                    "situation", command.getSituationName(),
                    "option", command.getOptionName(),
                    "words", String.join(", ", command.getVocList()),
                    "type", "content"
            );

            PromptTemplate userPromptTemplate = new PromptTemplate(userResource);

            SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
            Message userMessage = userPromptTemplate.createMessage(userModel);
            Message systemMessage = systemPromptTemplate.createMessage();
            Prompt prompt = new Prompt(List.of(systemMessage, userMessage));


            return chatClient.prompt(prompt)
                    .call()
                    .entity(new ParameterizedTypeReference<List<AIReviewReadDTO>>() {
                    });


        } catch (BusinessException e) {
            log.error("AI阅读内容生成失败: {}", e);
            throw e;
        } catch (Exception e) {
            log.error("AI阅读内容生成失败", e);
            throw new BusinessException(ResultCodeEnum.FAIL);
        }
    }

}
